home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Audio-DSP / NU / Source / FinderManager.m < prev    next >
Encoding:
Text File  |  1992-12-29  |  10.0 KB  |  333 lines

  1. #import "FinderManager.h"
  2. #import "WorkspaceManager.h"
  3. #import <appkit/Application.h>
  4. #import <appkit/NXBrowser.h>
  5. #import <appkit/NXBrowserCell.h>
  6. #import <appkit/Text.h>
  7. #import <appkit/Matrix.h>
  8. #import <appkit/publicWraps.h>
  9. #import <appkit/PopUpList.h>
  10. #import <appkit/Matrix.h>
  11. #import <objc/Storage.h>
  12. #import <regex.h>
  13. #import <strings.h>
  14. #import <libc.h>
  15.  
  16. #define MAXFINDERCELLLEN 80
  17. extern void NuGets() ;
  18.  
  19. @implementation FinderManager: Object
  20. {  id finderLineTextField,
  21.       findText,
  22.       replaceText,
  23.       caseSwitch,
  24.       regExpSwitch, 
  25.       selScopeSwitch,
  26.       lineNumBrowser ;
  27. }
  28.  
  29. - (int)browser:sender fillMatrix:matrix inColumn:(int)column ;
  30. { // delegate method for browser object 
  31.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  32.       return [[[NXApp mainWindow] lineList] count] ;
  33.   return 0 ;
  34. }
  35.  
  36. - browser:sender loadCell:cell atRow:(int)row inColumn:(int)column ;
  37. {  if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  38.    { int i,lineNum, charNum ; 
  39.      id theView ; 
  40.      char buf1[MAXFINDERCELLLEN+10], buf2[MAXFINDERCELLLEN + 17] ;
  41.      theView = [[NXApp mainWindow] textView] ;   
  42.      lineNum = * (int *) [[[NXApp mainWindow] lineList] elementAt: row] ;
  43.      charNum = [theView positionFromLine: lineNum] ;
  44.      [theView getSubstring: buf1 start: charNum length: MAXFINDERCELLLEN] ;
  45.      for(i = 0 ; i < MAXFINDERCELLLEN ; i++)
  46.      { if(buf1[i] == '\n') // don't grab more than 1 line...
  47.        { buf1[i] = '\0' ;
  48.          break ;
  49.        }
  50.      }
  51.      buf1[i] = '\0' ; // make sure null terminated!
  52.      sprintf(buf2,"%-5d %s",lineNum,buf1) ;
  53.      [cell setStringValue: buf2] ;
  54.      [cell setLeaf:YES] ;
  55.   }
  56.   return self ;
  57. }
  58.  
  59. - find: (char *) text regEx: (BOOL) regEx caseSensitive: (BOOL) caseSensitive inSelection: (BOOL) inSelection ;
  60. { // find the next occurence of "text" in the textview of the
  61.   // current mainWindow, provided in inherits from WorkspaceManager.  Text may contain
  62.   // a regular expression.  The search may be case sensitive.  The search may be
  63.   // confined to the current selection.  Returns nil if text is not found, else
  64.   // makes the text the current selection.    
  65.   id myWin = [lineNumBrowser window] ;
  66.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  67.   { int origLen, newLen ;
  68.     long firstStart, lastStart ; 
  69.     BOOL wrapped = NO ;
  70.     char textBuf[1024] ;
  71.     origLen = newLen = strlen(text) ;
  72.     if(!regEx) 
  73.       newLen *= 2 ; // not a rexp:leave room to quote everything
  74.     { int i,j  ;
  75.       char specialChars[] = "[]^*$\\." ; 
  76.       struct regex *ex ;
  77.       NXStream *aStream ;
  78.       NXSelPt start, end ;
  79.       char regexText[newLen+1] ;
  80.       id aView ;
  81.       if(!regEx) 
  82.       { for(i = 0,j = 0 ; text[i] ; i++,j++)
  83.         { if(index(specialChars,text[i])) // if a special char,
  84.             regexText[j++] = '\\' ; // then turn off its special meaning by 
  85.           regexText[j] = text[i] ; // quoting it.
  86.         }
  87.         regexText[j] = '\0' ;
  88.       }
  89.       else
  90.         strcpy(regexText,text) ;
  91.       ex = re_compile(regexText,caseSensitive) ;
  92.       aView = [[NXApp mainWindow] textView] ;
  93.       [aView getSel: &start :&end] ;
  94.       if(!inSelection) // scope is entire file
  95.       {  aStream = [[[NXApp mainWindow] textView] stream] ;
  96.         // search begins after current selection
  97.         firstStart = lastStart = (long) end.cp ;
  98.       }
  99.       else // scope is selection only
  100.       {  int len = end.cp - start.cp ;
  101.         { char aBuf[len + 1] ;
  102.           aStream = NXOpenMemory(NULL, 0, NX_READWRITE) ;
  103.           [aView getSubstring: aBuf start: start.cp length: len] ;
  104.           NXWrite(aStream, aBuf, len) ;
  105.           // search begins at beginning of stream
  106.           firstStart = lastStart = 0 ;
  107.         }
  108.       }
  109.       NXSeek(aStream, lastStart, NX_FROMSTART) ;
  110.       NuGets(aStream,textBuf) ;
  111.       do
  112.       { if(re_match(textBuf,ex))
  113.         { if(inSelection)
  114.           {  [aView setSel:(int) (lastStart + ex->start -
  115.                (int) textBuf + start.cp)
  116.                :(int) (lastStart + ex->end)-
  117.                (int) textBuf + start.cp] ;       
  118.              NXCloseMemory(aStream, NX_FREEBUFFER) ;
  119.           }
  120.           else
  121.             [aView setSel:(int) (lastStart + ex->start - (int) textBuf)
  122.                        :(int) (lastStart + ex->end)- (int) textBuf] ;
  123.           [aView scrollSelToVisible] ;
  124.           free(ex) ;
  125.           [[NXApp mainWindow] makeKeyAndOrderFront: self] ;
  126.           return self ;
  127.         }
  128.         if(NXAtEOS(aStream)) // wrap around to beginning
  129.         { NXSeek(aStream, 0L,NX_FROMSTART) ;
  130.           wrapped = YES ;
  131.         }
  132.         lastStart = NXTell(aStream) ;
  133.         NuGets(aStream,textBuf) ;
  134.       } while(!(wrapped && (lastStart >= firstStart))) ;
  135.       free(ex) ;
  136.       if(inSelection)
  137.          NXCloseMemory(aStream, NX_FREEBUFFER) ;
  138.       NXBeep() ;
  139.       [myWin setTitle: "Not Found"] ;
  140.       NXPing() ;
  141.       usleep(500000) ;
  142.       [myWin setTitle: "Find"] ;
  143.       return nil ;
  144.     }
  145.   }
  146.   else
  147.   { NXBeep() ;
  148.     [myWin setTitle: "What window?"] ;
  149.     NXPing() ;
  150.     usleep(500000) ;
  151.     [myWin setTitle: "Find"] ;
  152.   }
  153.   return self ;
  154. }
  155.  
  156.  
  157. - finderAddLine: sender ;
  158. { // add the current line to the list of lines
  159.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  160.   { id theView ;
  161.     NXSelPt start, end ;
  162.     theView = [[NXApp mainWindow] textView] ;
  163.     [theView getSel: &start :&end] ;
  164.     [[NXApp mainWindow] addToLineList: [theView lineFromPosition: start.cp]] ;
  165.     [lineNumBrowser loadColumnZero] ;
  166.   }
  167.   return self ;
  168. }
  169.  
  170. - finderBrowserHit: sender ;
  171. { NXEvent * anEvent ;
  172.   anEvent = [NXApp currentEvent] ;
  173.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  174.      /* if you want to fire on double clicks, use this: 
  175.         if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]]
  176.        && anEvent->data.mouse.click == 2) */
  177.   { char aBuf[MAXFINDERCELLLEN+17] ;
  178.     int lineNum ;
  179.     [lineNumBrowser setPathSeparator: ' '] ;
  180.     [lineNumBrowser getPath: aBuf toColumn: 1] ;
  181.     if(sscanf(aBuf,"%d",&lineNum))
  182.     { id aView ;
  183.       aView = [[NXApp mainWindow] textView] ;
  184.       [aView setSel: [aView positionFromLine: lineNum]
  185.                   : [aView positionFromLine: lineNum + 1]] ;
  186.       [aView scrollSelToVisible] ;
  187.       [[NXApp mainWindow] makeKeyAndOrderFront: self] ;
  188.     }
  189.   }
  190.   return self ;
  191. }
  192.  
  193. - finderCurrent: sender ;
  194. { // put line number of beginning of selection into
  195.   // the finderLineTextField 
  196.   id aView ;
  197.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  198.   { NXSelPt start,end ;
  199.     aView = [[NXApp mainWindow] textView] ;
  200.     [aView getSel: &start :&end] ;
  201.     [finderLineTextField setIntValue: [aView lineFromPosition: start.cp]] ;
  202.   }
  203.   return self ;
  204. }
  205.  
  206. - finderGoTo: sender ;
  207. { // set selection at beginning of line indicated by
  208.   // finderLineTextField 
  209.   id aView ;
  210.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  211.   { int pos1, pos2, lineNum ;
  212.     aView = [[NXApp mainWindow] textView] ;
  213.     pos1 = [aView positionFromLine:lineNum = [finderLineTextField intValue]] ;
  214.     pos2 = [aView positionFromLine: lineNum + 1] ;
  215.     [aView setSel:pos1 :pos2] ;
  216.     [aView scrollSelToVisible] ;
  217.     [finderLineTextField selectText: self] ;
  218.     [[NXApp mainWindow] makeKeyAndOrderFront: self] ;
  219.   }
  220.   return self ;
  221. }
  222.  
  223. struct MenuDefs
  224. { @defs(Menu)
  225. } ;
  226.  
  227. - finderNext: sender ;
  228. { // find the next occurence of the "find" text.
  229.   // returns nil if unable. Note the contortions
  230.   // needed to get the id of the current pop-up
  231.   // list selection...the trouble is NeXT give
  232.   // no method to obtain a Menu's Matrix
  233.   // so have to grab it from the ivar
  234.   struct MenuDefs *reg, *cas, *sel ;
  235.   reg = (struct MenuDefs *) regExpSwitch ;
  236.   cas = (struct MenuDefs *) caseSwitch ;
  237.   sel = (struct MenuDefs *) selScopeSwitch ;
  238.   return [self find: (char *) [findText stringValue]
  239.     regEx: [[reg->matrix selectedCell] tag]
  240.     caseSensitive: ![[cas->matrix selectedCell] tag]
  241.     inSelection: [[sel->matrix selectedCell] tag]] ;
  242. }
  243.  
  244.  
  245.  
  246. - finderRemLine: sender ;
  247. { // remove the browser-selected line from the list of lines
  248.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  249.   { [[NXApp mainWindow] removeFromLineList: [[lineNumBrowser matrixInColumn:0] selectedRow]] ;
  250.     [lineNumBrowser loadColumnZero] ;
  251.   }
  252.   return self ;
  253. }
  254.  
  255. - finderReplace: sender ;
  256. { // replace the highlighted text with the current text
  257.   id aView ;
  258.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  259.   { aView = [[NXApp mainWindow] textView] ;
  260.     [aView replaceSel: [replaceText stringValue]] ;
  261.   }
  262.   return self ;
  263. }
  264.  
  265. - finderReplaceAll: sender ;
  266. { // replace all occurences of the find text with the replace text
  267.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  268.   { struct MenuDefs *sel ;
  269.     sel = (struct MenuDefs *) selScopeSwitch ;
  270.     if(![[sel->matrix selectedCell] tag])
  271.     { if([self finderNext: self])
  272.        while([self finderReplaceAndFind: self]) ;
  273.     }
  274.     else // scope is entire file
  275.     { NXSelPt start, end ;
  276.       id aView ;
  277.       int diff ;
  278.       diff = strlen([replaceText stringValue]) -
  279.              strlen([findText stringValue]) ; 
  280.       aView = [[NXApp mainWindow] textView] ;
  281.       [aView getSel:&start :&end] ;
  282.       while([self finderNext: self])
  283.       { end.cp += diff ;
  284.         [self finderReplace: self] ;
  285.         // must reset the (adjusted) selection
  286.         [aView setSel: start.cp :end.cp] ;        
  287.       }
  288.     }
  289.   }
  290.   return self ;
  291.   
  292. }
  293.  
  294. - finderReplaceAndFind: sender ;
  295. { // replace the highlighted text with the replacement text,
  296.   // find next occurence of find text
  297.   if([[NXApp mainWindow] isKindOf: [WorkspaceManager class]])
  298.   { [self finderReplace: self] ;
  299.     return [self finderNext: self] ;
  300.   }
  301.   return self ;
  302. }
  303.  
  304. - findLine ;
  305. { return finderLineTextField ;
  306. }
  307.  
  308. - findText ;
  309. { return findText ;
  310. }
  311.  
  312. - init ;
  313. { // IB sends us our popupList's trigger id, not the popupLists
  314.   // themselves
  315.   [super init] ;
  316.   caseSwitch = [caseSwitch target] ;
  317.   regExpSwitch = [regExpSwitch target] ;
  318.   selScopeSwitch = [selScopeSwitch target] ;
  319.   return self ;
  320. }
  321.  
  322. - lineNumBrowser ;
  323. { return lineNumBrowser ;
  324. }
  325.  
  326. - setTheFindText: (char *) theText ;
  327. { // set the find text to theText
  328.   [findText setStringValue: theText] ;
  329.   return self ;
  330. }
  331.  
  332. @end
  333.